package com.gywj.race.util;

import com.google.common.collect.Maps;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.common.StringUtils;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 二维码工具
 */
public class QRCodeUtil {

    private static final Logger logger = LoggerFactory.getLogger(QRCodeUtil.class);

    /**
     * 二维码的宽
     */
    private static final int WIDTH = 250;
    /**
     * 二维码的高
     */
    private static final int HEIGHT = 250;
    /**
     * 中间图片的宽
     */
    private static final int LOGOWIDTH = 60;
    /**
     * 圆角半径
     */
    private static final int RADIUS = 10;
    /**
     * 留白填充宽度
     */
    private static final int MARGIN = 4;
    /**
     * 前色
     * 0x00808080;
     */
    private static final int FRONTCOLOR = 0x00000000;

    /**
     * 获取头像图像缓冲流
     *
     * @param avatarUrl 头像url
     * @return
     */
    public static BufferedImage generateAvatar(String avatarUrl) {
        InputStream avatarIs = null;
        try {
            logger.info("=============generateAvatar========" + avatarUrl);
            avatarIs = HttpClient.sendHttpByGet(avatarUrl);
            return ImageIO.read(avatarIs);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (avatarIs != null) {
                try {
                    avatarIs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * 默认生成二维码logo
     *
     * @param avatar    微信头像地址,作为logo
     * @param qrCodeUrl 微信生成的二维码地址
     */
    public static BufferedImage generateQRCodeLogo(String avatar, String qrCodeUrl) {
        return generateQRCodeLogo(avatar, qrCodeUrl, WIDTH, HEIGHT);
    }

    public static BufferedImage generateQRCodeDefault(String qrCodeUrl) {
        return generateQRCodeLogo(null, qrCodeUrl, WIDTH, HEIGHT);
    }

    public static BufferedImage generateQRCodeLogo(String avatarUrl, String qrCodeUrl, int width, int height) {
        InputStream avatarIs = null;
        try {
            if (!org.apache.commons.lang3.StringUtils.isEmpty(avatarUrl)) {
                avatarIs = HttpClient.sendHttpByGet(avatarUrl);
            }
            Map<EncodeHintType, Object> hints = Maps.newHashMap();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            // 修正容量高
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q);
            // 边框留白
            hints.put(EncodeHintType.MARGIN, 1);
            BitMatrix matrix = new MultiFormatWriter().encode(qrCodeUrl, BarcodeFormat.QR_CODE, width, height, hints);
            return proc(matrix, FRONTCOLOR, avatarIs);
        } catch (WriterException e) {
            e.printStackTrace();
        } finally {
            if (avatarIs != null) {
                try {
                    avatarIs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }


    /**
     * 解析微信二维码,获取微信二维码中的内容（url）
     *
     * @param qrCodeInputStream 微信二维码输入流
     * @return 微信二维码中的内容（url）
     */
    public static String decode(InputStream qrCodeInputStream) {
        MultiFormatReader multiFormatReader = new MultiFormatReader();
        BufferedImage image = null;
        BinaryBitmap binaryBitmap = null;
        try {
            image = ImageIO.read(qrCodeInputStream);
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            Binarizer binarizer = new HybridBinarizer(source);
            binaryBitmap = new BinaryBitmap(binarizer);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
        }
        while (image == null) {
            try {
                TimeUnit.MILLISECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Map hints = Maps.newHashMap();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            Result result = multiFormatReader.decode(binaryBitmap, hints);
            return result.getText();
        } catch (NotFoundException e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 图像缓冲流
     *
     * @param matrix            位矩阵
     * @param frontColor        前色
     * @param avatarInputStream 微信二维码输入流
     */
    private static BufferedImage proc(BitMatrix matrix, int frontColor, InputStream avatarInputStream) {
        int width = matrix.getWidth();
        // 处理后图片的数据
        int[] pixels = new int[width * width];
        // 中间图片数组数据
        int src[][] = null;
        boolean hashlogo = false;
        if (avatarInputStream != null) {
            src = getPic(avatarInputStream);
            hashlogo = true;
        }
        // 填充色-白色
        int margincolor = 0xffffffff;
        int w_half = width / 2;
        int frame = MARGIN;
        int img_half = LOGOWIDTH / 2;
        int r = RADIUS;
        //101
        int near = width / 2 - img_half - frame + r;
        //149
        int far = width / 2 + img_half + frame - r;
        for (int y = 0; y < width; y++) {
            for (int x = 0; x < width; x++) {
                if (!hashlogo) {
                    // 二维码
                    pixels[y * width + x] = matrix.get(x, y) ? frontColor : margincolor;
                } else {
                    // 中间图片
                    if (x > w_half - img_half && x < w_half + img_half
                            && y > w_half - img_half && y < w_half + img_half) {
                        pixels[y * width + x] = src[x - w_half + img_half][y - w_half + img_half];

                    } else if ((x > w_half - img_half - frame // 左边框
                            && x < w_half - img_half + frame && y > w_half - img_half - frame && y < w_half
                            + img_half + frame)
                            || (x > w_half + img_half - frame // 右边框
                            && x < w_half + img_half + frame
                            && y > w_half - img_half - frame && y < w_half + img_half
                            + frame)
                            || (x > w_half - img_half - frame // 上边框
                            && x < w_half + img_half + frame
                            && y > w_half - img_half - frame && y < w_half - img_half
                            + frame)
                            || (x > w_half - img_half - frame // 下边框
                            && x < w_half + img_half + frame
                            && y > w_half + img_half - frame && y < w_half + img_half
                            + frame)) {

                        // 圆角处理
                        if (x < near && y < near && (near - x) * (near - x) + (near - y) * (near - y) > r * r) {
                            // 左上圆角
                            pixels[y * width + x] = matrix.get(x, y) ? frontColor : margincolor;
                        } else if (x > far && y < near && (x - far) * (x - far) + (near - y) * (near - y) > r * r) {
                            // 右上圆角
                            pixels[y * width + x] = matrix.get(x, y) ? frontColor : margincolor;
                        } else if (x < near && y > far && (near - x) * (near - x) + (y - far) * (y - far) > r * r) {
                            // 左下圆角
                            pixels[y * width + x] = matrix.get(x, y) ? frontColor : margincolor;
                        } else if (x > far && y > far && (x - far) * (x - far) + (y - far) * (y - far) > r * r) {
                            // 右下圆角
                            pixels[y * width + x] = matrix.get(x, y) ? frontColor : margincolor;
                        } else {
                            // 边框填充颜色
                            pixels[y * width + x] = margincolor;
                        }
                    } else {
                        // 二维码
                        pixels[y * width + x] = matrix.get(x, y) ? frontColor : margincolor;
                    }
                }
            }
        }
        BufferedImage image = new BufferedImage(width, width, BufferedImage.TYPE_INT_RGB);
        image.getRaster().setDataElements(0, 0, width, width, pixels);
        return image;
    }

    /**
     * 图片的压缩、圆角处理,并生成数组
     *
     * @param avatarInputStream logo的输入流
     * @return
     */
    public static int[][] getPic(InputStream avatarInputStream) {
        BufferedImage biSrc = null;
        try {
            biSrc = ImageIO.read(avatarInputStream);
        } catch (IOException e) {

        }
        BufferedImage biTarget = new BufferedImage(LOGOWIDTH, LOGOWIDTH, BufferedImage.TYPE_3BYTE_BGR);
        Graphics graphics = biTarget.getGraphics();
        graphics.drawImage(biSrc.getScaledInstance(LOGOWIDTH, LOGOWIDTH, Image.SCALE_SMOOTH), 0, 0, null);
        graphics.dispose();
        int src[][] = new int[LOGOWIDTH][LOGOWIDTH];
        // 圆角处理半径
        int r = RADIUS;
        int max = LOGOWIDTH;
        int bordercolor = 0x00000000;
        int whitecolor = 0xffffffff;
        for (int x = 0; x < LOGOWIDTH; x++) {
            for (int y = 0; y < LOGOWIDTH; y++) {
                if (x < r && y < r && ((r - x) * (r - x) + (r - y) * (r - y) > (r - 1) * (r - 1))) {
                    // 左上圆角
                    if ((r - x) * (r - x) + (r - y) * (r - y) > r * r) {
                        src[x][y] = whitecolor;
                    } else {
                        src[x][y] = bordercolor;
                    }
                } else if (x > (max - r) && y < r && (x + r - max) * (x + r - max) + (r - y) * (r - y) > (r - 1) * (r - 1)) {
                    // 右上圆角
                    if ((x + r - max) * (x + r - max) + (r - y) * (r - y) > r * r) {
                        src[x][y] = whitecolor;
                    } else {
                        src[x][y] = bordercolor;
                    }
                } else if (x < r && y > (max - r) && (r - x) * (r - x) + (y + r - max) * (y + r - max) > (r - 1) * (r - 1)) {
                    // 左下圆角
                    if ((r - x) * (r - x) + (y + r - max) * (y + r - max) > r * r) {
                        src[x][y] = whitecolor;
                    } else {
                        src[x][y] = bordercolor;
                    }
                } else if (x > (max - r) && y > (max - r) && (x + r - max) * (x + r - max) + (y + r - max) * (y + r - max) > (r - 1) * (r - 1)) {
                    // 右下圆角
                    if ((x + r - max) * (x + r - max) + (y + r - max) * (y + r - max) > r * r) {
                        src[x][y] = whitecolor;
                    } else {
                        src[x][y] = bordercolor;
                    }
                } else {
                    if (((x >= r && x <= max - r) && (y == 0 || y == 1 || y == max - 1 || y == max)) || ((y >= r && y <= max - r) && (x == 0 || x == 1 || x == max - 1 || x == max))) {
                        // 四周除圆角的边框
                        src[x][y] = bordercolor;
                    } else {
                        // 图片值
                        src[x][y] = biTarget.getRGB(x, y);
                    }
                }
            }
        }
        return src;
    }

}
